//
// Created by 🕊️ on 24-8-6.
//
#include <stdio.h>
#include <string.h>
#include <stdint.h>

#include "decrypt.h"
#include "zuc.h"

int char2hex(unsigned char* hex, char c) {
    if (c >= '0' && c <= '9') {
        *hex = c - '0';
        return 0;
    }
    if (c >= 'a' && c <= 'f') {
        *hex = c - 'a' + 10;
        return 0;
    }
    if (c >= 'A' && c <= 'F') {
        *hex = c - 'A' + 10;
        return 0;
    }
    return BAD_DATA;
}

int char2doublehex(unsigned char* hex, char c1, char c2) {
    unsigned char h[2];
    if (char2hex(&h[0], c1) || char2hex(&h[1], c2)) {
        return BAD_DATA;
    }
    *hex = (h[0] << 4) | h[1];
    return 0;
}

int str2hex(unsigned char* dest, const char* src, int len) {
    if (len % 2 != 0) return BAD_DATA;
    int half_len = len / 2;
    for (int i = 0; i < half_len; ++i) {
        if (char2doublehex(&dest[i], src[2 * i], src[2 * i + 1])) return BAD_DATA;
    }
    return 0;
}

int decrypt(DecryptedData *decrypted_data, const char *cipher_text, int len)
{
    unsigned char hex_data[256] = {0};
    if (str2hex(hex_data, cipher_text, len)) {
        return BAD_DATA;
    }

    unsigned char key[16] = {
        0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
        0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
    };
    unsigned char iv[16] = {
        0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
        0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
    };

    int segment_size = 256;

    // client cnt
    unsigned short client_N_S = 0;

    // server side define
    int server_N_S=0;
    unsigned char outbuf[256];
    ZUC_STATE zuc_state1 = {{0}};
    int step = 0;   // 失步数

    //	temp variable,
    unsigned char keybuf[256];

    // emulate the transfer action
    unsigned char transbuf[256];
//    CD outdata;

    // server side: init server's zuc state
    zuc_init(&zuc_state1, key, iv);
    memset(transbuf, 0, 256);
    memcpy(transbuf, hex_data, 12);

    // server side: receive transfer data and decipher it
    // printf("server side:\n");
    server_N_S++;

    outbuf[0] = transbuf[0];    //第0位是序列长度，这部分不参与加解密，作为先验信息直接传到接收端
    client_N_S = (0x00FF & transbuf[1]) | (0xFF00 & transbuf[2]);
    step = client_N_S - server_N_S;
    if(step != 0)   //同步
    {
        for(int i = 0; i < step; ++i)
        {
            zuc_generate_keystream(&zuc_state1, segment_size / 4, (uint32_t *) keybuf);
        }
    }
    zuc_generate_keystream(&zuc_state1, segment_size / 4, (uint32_t *) keybuf);
    gmssl_memxor(outbuf + 1, transbuf + 3, keybuf, outbuf[0]);
    decrypted_data->heart_rate = outbuf[1];
//    outdata.heartrate = outbuf[1];
    memcpy(decrypted_data->name, outbuf+2, 8);
//    printf("%s ", outdata.name);
//    printf("%d\n", outdata.heartrate);
//    printf("%s ", decrypted_data->name);
//    printf("%d\n", decrypted_data->heart_rate);

    return 0;
}

void print_decrypted_data(const DecryptedData *decrypted_data)
{
    printf("[DecryptedData]name:%s heart_rate:%d\n", decrypted_data->name, decrypted_data->heart_rate);
}

void build_wrapped_data(WrappedData *w, const DecryptedData *d) {
    memcpy(w->name, d->name, 8);
    w->heart_rate = d->heart_rate;
    time(&w->time);
}

void print_wrapped_data(const WrappedData *w) {
    struct tm* timeinfo = localtime(&w->time);
    printf("[WrappedData]name:%s heart_rate:%d time:%ld %s", w->name, w->heart_rate, w->time, asctime(timeinfo));
}